/**
 * 工具类
 * @author 王锦阳
 * @version 1.0
 * @since 2018/10/29
 */
import {HttpHeaders} from '@angular/common/http';

export class SystemUtils {

    /**
     * 克隆
     * @param obj
     */
    public static clone<T extends Object>(obj: T): T {
        if (!obj || !(obj instanceof Object)) {
            return obj;
        }
        return <T>JSON.parse(JSON.stringify(obj));
    }

    /**
     * 检查指定的值是否有效（不为null或者undefined）
     * @param value 待检查的值
     * @returns {boolean} 返回检查结果（true：有效，false：无效）
     */
    public static isValidValue(value: any): boolean {
        return value !== undefined && value !== null && value !== "undefined";
    }

    /**
     * 检查指定的值是否无效（为null或者undefined）
     * @param value 待检查的值
     * @returns {boolean} 返回检查结果（true：无效，false：有效）
     */
    public static isInvalidValue(value: any): boolean {
        return !SystemUtils.isValidValue(value);
    }

    /**
     * 去除字符串左右空格的函数
     * @param str 需要trim的字符串
     * @returns {string} 返回trim后的字符串
     */
    public static trim(str: string): string {
        return SystemUtils.isValidValue(str) ? str.trim() : str;
    }

    /**
     * <p>检查字符串是否为空白字符或空类型
     * <pre>
     * Utils.isEmpty(undefined) = true
     * Utils.isEmpty(null)      = true
     * Utils.isEmpty("")        = true
     * Utils.isEmpty(" ")       = true
     * Utils.isEmpty("bob")     = false
     * Utils.isEmpty("  bob  ") = false
     * </pre>
     * @param str 待检查的字符串
     * @returns {boolean} 返回检查结果（true：是，false：不是）
     */
    public static isBlank(str: string): boolean {
        return (str === undefined || str === null || SystemUtils.trim(str).length === 0);
    }


    /**
     * <p>检查字符串是否不为空白字符或空类型
     * <pre>
     * Utils.isEmpty(undefined) = false
     * Utils.isEmpty(null)      = false
     * Utils.isEmpty("")        = false
     * Utils.isEmpty(" ")       = false
     * Utils.isEmpty("bob")     = true
     * Utils.isEmpty("  bob  ") = true
     * </pre>
     * @param str 待检查的字符串
     * @returns {boolean} 返回检查结果（true：是，false：不是）
     */
    public static isNotBlank(str: string): boolean {
        return !SystemUtils.isBlank(str);
    }

    /**
     * <p>检查字符串是否为“”或者null / undefined
     * <pre>
     * Utils.isEmpty(undefined) = true
     * Utils.isEmpty(null) = true
     * Utils.isEmpty("") = true
     * Utils.isEmpty(" ") = false
     * Utils.isEmpty("bob") = false
     * Utils.isEmpty("  bob  ") = false
     * </pre>
     * @param str 待检查的字符串
     * @returns {boolean} 返回检查结果（true：是，false：不是）
     */
    public static isEmpty(str: string): boolean {
        return (str === undefined || str === null || str.length === 0);
    }


    /**
     * <p>检查字符串是否不为“”或者null / undefined
     * <pre>
     * Utils.isEmpty(undefined) = false
     * Utils.isEmpty(null)      = false
     * Utils.isEmpty("")        = false
     * Utils.isEmpty(" ")       = true
     * Utils.isEmpty("bob")     = true
     * Utils.isEmpty("  bob  ") = true
     * </pre>
     * @param str 待检查的字符串
     * @returns {boolean} 返回检查结果（true：是，false：不是）
     */
    public static isNotEmpty(str: string): boolean {
        return !SystemUtils.isEmpty(str);
    }


    /**
     * 检查指定标识位是否激活的函数
     * @param flag 标识值
     * @param bit 标识位
     * @return 返回检查结果（true：激活，false：未激活）
     */
    public static isActivateFlag(flag: number, bit: number): boolean {
        return (flag & (1 << bit)) !== 0;
    }

    /**
     * 激活指定标识位的函数
     * @param flag 标识值
     * @param bit 标识位
     * @return 返回激活后的值
     */
    public static activateFlag(flag: number, bit: number): number {
        return flag | (1 << bit);
    }

    /**
     * 反激活指定标识位的函数
     * @param flag 标识值
     * @param bit 标识位
     * @return 返回反激活后的值
     */
    public static deactivateFlag(flag: number, bit: number): number {
        return flag & (~(1 << bit));
    }

    /**
     * 对指定的字符串进行base64转码的函数
     * @param input 待转码的字符串
     * @return 返回转码后的base64编码
     */
    public static base64encoder(input: string): string {
        const _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        let output = "";
        let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        let i = 0;
        const _utf8_encode: Function = (string) => {
            string = string.replace(/\r\n/g, "\n");
            let utfText = "";
            for (let n = 0; n < string.length; n++) {
                const c = string.charCodeAt(n);
                if (c < 128) {
                    utfText += String.fromCharCode(c);
                } else if ((c > 127) && (c < 2048)) {
                    utfText += String.fromCharCode((c >> 6) | 192);
                    utfText += String.fromCharCode((c & 63) | 128);
                } else {
                    utfText += String.fromCharCode((c >> 12) | 224);
                    utfText += String.fromCharCode(((c >> 6) & 63) | 128);
                    utfText += String.fromCharCode((c & 63) | 128);
                }
            }
            return utfText;
        };
        input = _utf8_encode(input);
        while (i < input.length) {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            output = output +
                _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
                _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
        }
        return output;
    }

    /**
     * 对指定的base64编码字符串解码的函数
     * @param input 待解码的字符串
     * @return 返回解码后的字符串
     */
    public static base64decoder(input: string): string {
        const _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        let output = "";
        let chr1, chr2, chr3;
        let enc1, enc2, enc3, enc4;
        let i = 0;
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        while (i < input.length) {
            enc1 = _keyStr.indexOf(input.charAt(i++));
            enc2 = _keyStr.indexOf(input.charAt(i++));
            enc3 = _keyStr.indexOf(input.charAt(i++));
            enc4 = _keyStr.indexOf(input.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            output = output + String.fromCharCode(chr1);
            if (enc3 !== 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 !== 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        const _utf8_decode = (utfText: string) => {
            let string = "";
            let index = 0;
            let c1 = 0;
            let c2 = 0;
            let c3 = 0;
            while (index < utfText.length) {
                c1 = utfText.charCodeAt(index);
                if (c1 < 128) {
                    string += String.fromCharCode(c1);
                    index++;
                } else if ((c1 > 191) && (c1 < 224)) {
                    c2 = utfText.charCodeAt(index + 1);
                    string += String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
                    index += 2;
                } else {
                    c2 = utfText.charCodeAt(index + 1);
                    c3 = utfText.charCodeAt(index + 2);
                    string += String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                    index += 3;
                }
            }
            return string;
        };
        output = _utf8_decode(output);
        return output;
    }

    /**
     * 将指定图片文件转换为base64字符串的函数
     * @param files 文件列表
     */
    public static getBase64Image(files: File[]): Promise<string[]> {
        return new Promise<string[]>(resolve => {
            if (files.length === 0) {
                resolve([]);
                return;
            }
            const base64List: string[] = [];
            for (const file of files) {
                const reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = (evt) => {
                    base64List.push(<string> evt.target['result']);
                    resolve(base64List);
                };
            }
        });
    }

    /**
     * 显示/隐藏加载动画的函数
     * @param show 是否显示（true：显示，false：隐藏）
     */
    public static showLoading(show: boolean = true) {
        const loading: HTMLElement = document.getElementById("loading");
        if (show) {
            loading.style.display = 'block';
        } else {
            loading.style.display = 'none';
        }
    }

    public static toForm(obj: any) {
        let query = '';
        let value, fullSubName, subValue, innerObj, i;

        for (const name in obj) {
            if (!obj.hasOwnProperty(name)) {
                continue;
            }
            value = obj[name];
            if (value instanceof Array) {
                for (i = 0; i < value.length; ++i) {
                    subValue = value[i];
                    fullSubName = name + '[]';
                    innerObj = {};
                    innerObj[fullSubName] = subValue;
                    query += SystemUtils.toForm(innerObj) + '&';
                }
            } else if (value instanceof Date) {
                query += encodeURIComponent(name) + '=' + encodeURIComponent(value.toUTCString()) + '&';
            } else if (value instanceof Object) {
                for (const subName in value) {
                    if (!subName) {
                        continue;
                    }
                    subValue = value[subName];
                    fullSubName = name + '[' + subName + ']';
                    innerObj = {};
                    innerObj[fullSubName] = subValue;
                    query += SystemUtils.toForm(innerObj) + '&';
                }
            } else if (value !== undefined && value !== null) {
                query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
            }
        }
        return query.length ? query.substr(0, query.length - 1) : query;
    }

    public static getHeader() {
        return {
            headers: new HttpHeaders({
                'Content-Type': "application/x-www-form-urlencoded;charset=UTF-8"
            })
        };
    }

    public static parseDate(date: string|Date, hideTime: boolean = false) {
        if (typeof date === "string") {
            return date;
        }
        const year: number = date.getFullYear();
        let month: string = (date.getMonth() + 1) + '';
        month = month.length === 1 ? `0${month}` : month;
        let day: string = date.getDate() + '';
        day = day.length === 1 ? `0${day}` : day;
        let hour: string = date.getHours() + '';
        hour = hour.length === 1 ? `0${hour}` : hour;
        let minute: string = date.getMinutes() + '';
        minute = minute.length === 1 ? `0${minute}` : minute;
        if (hideTime) {
            return `${year}/${month}/${day}`;
        }
        return `${year}/${month}/${day} ${hour}:${minute}`;
    }
}
